home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Mac Game Programming Gurus
/
TricksOfTheMacGameProgrammingGurus.iso
/
Book Chapters
/
03 - Advanced Graphics
/
Example 6
/
update.c
< prev
next >
Wrap
Text File
|
1995-03-10
|
7KB
|
270 lines
//
// File: update.c
//
// This file contains routines to manage the update from the offscreen to the screen.
//
// 2/19/95 -- Created by Mick
//
// include files
#include "global.h"
#include "update.h"
// defines for this file
#define kMaxRects 10 // the maximum number of update rects
#define kInitialRects 10 // the initial number of update rects
// global function declarations
void clearUpdate( void );
void addRectToUpdate( Rect *inUpdateRect );
unsigned long getUpdateRectCount( void );
void getUpdateRect( unsigned long inRectIndex, Rect *outUpdateRect );
void increaseUpdateRects( void );
void decreaseUpdateRects( void );
// global data owned by this file
// local function declarations
static void adjustRect( Rect *ioRect );
// static data
static sNumUpdateRects = kInitialRects; // the number of update rects
static Rect sUpdateRects[ kMaxRects ]; // the rects that needs to be udpated
static unsigned long sUpdateRectCount; // how many update rects are there
// functions
//
// clearUpdate -
//
// Reset the update area to none.
//
void clearUpdate( void )
{
// note that there are no update rects
sUpdateRectCount = 0;
}
//
// addRectToUpdate -
//
// Adds a rect to the update area.
//
void addRectToUpdate( Rect *inUpdateRect )
{
Rect newRect; // the rect we are adding
unsigned long indexCounter; // a counter to scan the rect array
unsigned char xTouch; // do the rects intersect horizontally
unsigned char yTouch; // do the rects intersect vertically
unsigned long bestIndex; // the index of our best canidate rect
unsigned long bestArea; // the area of our best canidate rect
unsigned long scratchArea; // a temp area for calculations
Rect scratchRect; // a temp rect for calculations
Rect bestRect; // the best rect so far
// adjust the rect to 32 bit bounds
newRect = *inUpdateRect;
adjustRect( &newRect );
// scan the list and see if the rect touches any of the rects there
for( indexCounter = 0; indexCounter < sUpdateRectCount; indexCounter++ )
{
// do the rects touch?
// check horizontally
if ( newRect.left < sUpdateRects[ indexCounter ].left )
{
if ( newRect.right >= sUpdateRects[ indexCounter ].left )
{
xTouch = kTrue;
}
else
{
xTouch = kFalse;
}
}
else
{
if ( sUpdateRects[ indexCounter ].right >= newRect.left )
{
xTouch = kTrue;
}
else
{
xTouch = kFalse;
}
}
// check vertically
if ( newRect.top < sUpdateRects[ indexCounter ].top )
{
if ( newRect.bottom >= sUpdateRects[ indexCounter ].top )
{
yTouch = kTrue;
}
else
{
yTouch = kFalse;
}
}
else
{
if ( sUpdateRects[ indexCounter ].bottom >= newRect.top )
{
yTouch = kTrue;
}
else
{
yTouch = kFalse;
}
}
// if the rects do touch,
if ( yTouch && xTouch )
{
// join the rects into new rect
newRect.left = ( newRect.left < sUpdateRects[ indexCounter ].left ) ? newRect.left : sUpdateRects[ indexCounter ].left;
newRect.top = ( newRect.top < sUpdateRects[ indexCounter ].top ) ? newRect.top : sUpdateRects[ indexCounter ].top;
newRect.right = ( newRect.right > sUpdateRects[ indexCounter ].right ) ? newRect.right : sUpdateRects[ indexCounter ].right;
newRect.bottom = ( newRect.bottom > sUpdateRects[ indexCounter ].bottom ) ? newRect.bottom : sUpdateRects[ indexCounter ].bottom;
// remove the rect from the list
sUpdateRectCount -= 1;
for( ; indexCounter < sUpdateRectCount; indexCounter++ )
{
// shift the next rects down
sUpdateRects[ indexCounter ] = sUpdateRects[ indexCounter + 1 ];
}
// call this routine with the new, joined rect
addRectToUpdate( &newRect );
// we are done
return;
}
}
// if there is room, add this rect to the list
if ( sUpdateRectCount < sNumUpdateRects )
{
sUpdateRects[ sUpdateRectCount ] = newRect;
sUpdateRectCount++;
}
else
{
// otherwise find the rect where the union is the smallest delta
bestIndex = 0;
bestArea = 0xFFFFFFFF; // a very big area
for( indexCounter = 0; indexCounter < sUpdateRectCount; indexCounter++ )
{
// create the unified rect
scratchRect.left = ( newRect.left < sUpdateRects[ indexCounter ].left ) ? newRect.left : sUpdateRects[ indexCounter ].left;
scratchRect.top = ( newRect.top < sUpdateRects[ indexCounter ].top ) ? newRect.top : sUpdateRects[ indexCounter ].top;
scratchRect.right = ( newRect.right > sUpdateRects[ indexCounter ].right ) ? newRect.right : sUpdateRects[ indexCounter ].right;
scratchRect.bottom = ( newRect.bottom > sUpdateRects[ indexCounter ].bottom ) ? newRect.bottom : sUpdateRects[ indexCounter ].bottom;
// determine how much this will grow the rect
scratchArea = ( scratchRect.right - scratchRect.left ) * ( scratchRect.bottom - scratchRect.top ) -
( sUpdateRects[ indexCounter ].right - sUpdateRects[ indexCounter ].left ) *
( sUpdateRects[ indexCounter ].bottom - sUpdateRects[ indexCounter ].top );
// if this area is smaller than the best so far, keep it
if ( scratchArea < bestArea )
{
bestArea = scratchArea;
bestIndex = indexCounter;
bestRect = scratchRect;
}
}
// save our best canidate
sUpdateRects[ bestIndex ] = bestRect;
}
}
//
// getUpdateRectCount -
//
// Get the number of update rects.
//
unsigned long getUpdateRectCount( void )
{
return sUpdateRectCount;
}
//
// getUpdateRect -
//
// Return the update rect specified.
//
void getUpdateRect( unsigned long inRectIndex, Rect *outUpdateRect )
{
// return the correct rect
*outUpdateRect = sUpdateRects[ inRectIndex ];
}
//
// increaseUpdateRects -
//
// Increase the number of update rects. Never go above kMaxRects.
//
void increaseUpdateRects( void )
{
// make sure that we are not already at the maximum
if ( sNumUpdateRects == kMaxRects )
{
return;
}
// increase the number
sNumUpdateRects++;
}
//
// decreaseUpdateRects -
//
// Decrease the number of update rects. Never go below 1.
//
void decreaseUpdateRects( void )
{
// make sure that we are not already at the minumum
if ( sNumUpdateRects == 1 )
{
return;
}
// increase the number
sNumUpdateRects--;
}
//
// adjustRect -
//
// Move the left and right sides to 32 bit boundrys. This will speed up CopyBits.
//
void adjustRect( Rect *ioRect )
{
// expand the rect so its horizontal sides are on 32 bit bounds
ioRect->left = ioRect->left & 0xfffC;
ioRect->right = ( ioRect->right + 3 ) & 0xfffC;
}